﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace await
{
    class Program
    {

        //static async Task Main(string[] args)
        //{
        //    await callMethod();
        //    Console.ReadKey();
        //}

        //public static async Task callMethod()
        //{
        //    Method2();
        //    var count = await Method1();
        //    Method3(count);
        //}

        //public static async Task<int> Method1()
        //{
        //    int count = 0;
        //    await Task.Run(() =>
        //    {
        //        for (int i = 0; i < 100; i++)
        //        {
        //            Console.WriteLine(" Method 1");
        //            count += 1;
        //        }
        //    });
        //    return count;
        //}

        //public static void Method2()
        //{
        //    for (int i = 0; i < 25; i++)
        //    {
        //        Console.WriteLine(" Method 2");
        //    }
        //}

        //public static void Method3(int count)
        //{
        //    Console.WriteLine("Total count is " + count);
        //}

        /*
         --开始!
         --下面我（主线程）先通知下儿子（子线程）也开始。 我的 ID：1
         --我刚到，还没找到儿子（子线程）的房间，我的 ID：1
             主线程遇到var result = await WasteTime()；  这里同AsyncTask()，仍然由主线程执行WasteTime()
         --我终于找到了，下面准备让儿子（子线程）开干！我的 ID：1
             主线程遇到await Task.Run()。开启子线程执行委托。函数WasteTime()中，await Task.Run()使用了await，开的子线程不会阻塞主线程，函数WasteTime()会
             立马返回一个未完成的Task，回到函数AsyncTask()中的await WasteTime()。   函数AsyncTask()中，var result = await WasteTime()也使用了await，
             故函数AsyncTask()也会立马返回未完成的Task，回到Main中的AsyncTask()这句，而Main没使用await修饰，故从AsyncTask()往下执行
         儿子（子线程）开始异步执行了! 我的 ID：    // 这是因为主线程和子线程并发执行，而主线程回到Main后先sleep200，所以先输出这句 
         --我（主线程）已经让我儿子（子线程）开始工作了，我也继续工作
         --我（主线程）完成! 我的 ID：1
             子线程执行完委托后，再执行await WasteTime();后面的代码
         儿子（子线程）异步执行完了。我的 ID：3
         儿子（子线程）已经干完了应该干的事情! 我的 ID：3
         */
        static void Main(string[] args)
        {
            Console.WriteLine("--开始!");
            Console.WriteLine($"--下面我（主线程）先通知下儿子（子线程）也开始。 我的 ID：{Thread.CurrentThread.ManagedThreadId}");

            AsyncTask(); // AsyncTask()虽然是一个异步方法（被async修饰，且函数体中使用了await），但并不会自己创建线程。
                         // 这里也没有创建线程去执行AsyncTask()，所以仍然由主线程执行。
            Thread.Sleep(200);
            Console.WriteLine("--我（主线程）已经让我儿子（子线程）开始工作了，我也继续工作");
            Console.WriteLine($"--我（主线程）完成! 我的 ID：{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadLine();
        }
         
        public static async Task AsyncTask()
        {
            Thread.Sleep(1000);
            Console.WriteLine($"--我刚到，还没找到儿子（子线程）的房间，我的 ID：{Thread.CurrentThread.ManagedThreadId}");
            var result = await WasteTime(); // 刚到这里时不会立马返回，因为还没开启子线程异步执行
            Console.WriteLine(result);
            Console.WriteLine($"儿子（子线程）已经干完了应该干的事情! 我的 ID：{Thread.CurrentThread.ManagedThreadId}");
        }
        // async 修饰的方法，也就是异步方法，不占用主线程
        private static async Task<string> WasteTime()
        {
            Console.WriteLine($"--我终于找到了，下面准备让儿子（子线程）开干！我的 ID：{Thread.CurrentThread.ManagedThreadId}");
            return await Task.Run(() => // 创建一个子线程
            {
                Console.WriteLine($"儿子（子线程）开始异步执行了! 我的 ID：{Thread.CurrentThread.ManagedThreadId}");
                // 模拟耗时操作
                Thread.Sleep(5000);
                return $"儿子（子线程）异步执行完了。我的 ID：{Thread.CurrentThread.ManagedThreadId}";
            });
        }


        //public static async Task Main()
        //{
        //    Console.WriteLine("Main 开始（主线程 ID: " + Thread.CurrentThread.ManagedThreadId + ")");
        //    await Level1Async(); // 第一层异步调用
        //    Console.WriteLine("Main 结束（主线程 ID: " + Thread.CurrentThread.ManagedThreadId + ")");
        //    Console.ReadLine();
        //}

        //public static async Task Level1Async()
        //{
        //    Console.WriteLine("Level1Async 开始（线程 ID: " + Thread.CurrentThread.ManagedThreadId + ")");
        //    await Level2Async(); // 第二层异步调用
        //    Console.WriteLine("Level1Async 结束（线程 ID: " + Thread.CurrentThread.ManagedThreadId + ")");
        //}

        //public static async Task Level2Async()
        //{
        //    Console.WriteLine("Level2Async 开始（线程 ID: " + Thread.CurrentThread.ManagedThreadId + ")");
        //    //await Task.Delay(1000); // 第三层异步操作（模拟耗时操作）
        //    await Task.Run(() => Thread.Sleep(1000));
        //    Console.WriteLine("Level2Async 结束（线程 ID: " + Thread.CurrentThread.ManagedThreadId + ")");
        //}

    }
}
